﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using Miris.HumanMilkAnalyser.DataModel;
using Miris.HumanMilkAnalyser.Service.Interface;
using Miris.HumanMilkAnalyser.Service.Shared;
using Miris.HumanMilkAnalyser.WPF.Model;
using Miris.HumanMilkAnalyser.WPF.Shared;

namespace Miris.HumanMilkAnalyser.WPF.ViewModel
{
    /// <summary>
    /// This class contains properties that a View can data bind to.
    /// <para>
    /// See http://www.galasoft.ch/mvvm
    /// </para>
    /// </summary>
    public class UnassignedSampleNumberListViewModel : MyViewModelBase
    {
        public const string DeleteDataConfirmMessageToken = "UnassignedSampleNumberListDeleteDataConfirm";
        private IUnassignedSampleNumberService _unassignedSampleNumberService;

        /// <summary>
        /// Initializes a new instance of the UnassignedSampleNumberListViewModel class.
        /// </summary>
        public UnassignedSampleNumberListViewModel(IDataService dataService)
            : base(dataService)
        {
            _unassignedSampleNumberService = ServiceFactory.CreateUnassignedSampleNumberService();
        }

        public override void ResetProperties()
        {
            base.ResetProperties();

            StartDate = GeneralUtility.GetCurrentDateTime();
            EndDate = GeneralUtility.GetCurrentDateTime();
            UnassignedSampleNumberList.Clear();
        }

        /// <summary>
        /// The <see cref="StartDate" /> property's name.
        /// </summary>
        public const string StartDatePropertyName = "StartDate";

        private DateTime _startDate = GeneralUtility.GetCurrentDateTime();

        /// <summary>
        /// Sets and gets the StartDate property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public DateTime StartDate
        {
            get
            {
                return _startDate;
            }

            set
            {
                if (_startDate == value)
                {
                    return;
                }

                RaisePropertyChanging(StartDatePropertyName);
                _startDate = value;
                RaisePropertyChanged(StartDatePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="EndDate" /> property's name.
        /// </summary>
        public const string EndDatePropertyName = "EndDate";

        private DateTime _endDate = GeneralUtility.GetCurrentDateTime();

        /// <summary>
        /// Sets and gets the EndDate property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public DateTime EndDate
        {
            get
            {
                return _endDate;
            }

            set
            {
                if (_endDate == value)
                {
                    return;
                }

                RaisePropertyChanging(EndDatePropertyName);
                _endDate = value;
                RaisePropertyChanged(EndDatePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="UnassignedSampleNumberList" /> property's name.
        /// </summary>
        public const string UnassignedSampleNumberListPropertyName = "UnassignedSampleNumberList";

        private ObservableCollection<UnassignedSampleNumberViewModel> _unassignedSampleNumberList = 
            new ObservableCollection<UnassignedSampleNumberViewModel>();

        /// <summary>
        /// Sets and gets the UnassignedSampleNumberList property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public ObservableCollection<UnassignedSampleNumberViewModel> UnassignedSampleNumberList
        {
            get
            {
                return _unassignedSampleNumberList;
            }

            set
            {
                if (_unassignedSampleNumberList == value)
                {
                    return;
                }

                RaisePropertyChanging(UnassignedSampleNumberListPropertyName);
                _unassignedSampleNumberList = value;
                RaisePropertyChanged(UnassignedSampleNumberListPropertyName);
            }
        }

        private RelayCommand _searchCommand;

        /// <summary>
        /// Gets the SearchCommand.
        /// </summary>
        public RelayCommand SearchCommand
        {
            get
            {
                return _searchCommand ?? (_searchCommand = new RelayCommand(
                    ExecuteSearchCommand,
                    CanExecuteSearchCommand));
            }
        }

        private void ExecuteSearchCommand()
        {
            try
            {
                var selectedStartDate = StartDate.Date;
                var selectedEndDate = new DateTime(EndDate.Year, EndDate.Month, EndDate.Day, 23, 59, 59);

                // Get the data from data source based on provided date range.
                var matchedUnassignedSampleNumbers = _unassignedSampleNumberService
                    .Query(p => p.GenerateDate >= selectedStartDate && p.GenerateDate <= selectedEndDate).
                    OrderByDescending(p => p.GenerateDate).ToList();

                UnassignedSampleNumberList.Clear();

                // Fill the ObservableCollection for binding
                for (int i = 0; i < matchedUnassignedSampleNumbers.Count; i++)
                {
                    UnassignedSampleNumberList.Add(new UnassignedSampleNumberViewModel(null)
                    {
                        SequenceNumber = i + 1,
                        SampleNumber = matchedUnassignedSampleNumbers[i].SampleNumber,
                        GenerateDateDisplay = matchedUnassignedSampleNumbers[i].GenerateDate.ToString(GeneralUtility.LongDateTimeFormat)
                    });
                }
            }
            catch (Exception ex)
            {
                RequestDisplayErrorMessage(ex.Message);
            }
        }

        private bool CanExecuteSearchCommand()
        {
            // If StartDate is less than or equal than EndDate.
            return StartDate <= EndDate;
        }

        private RelayCommand<IEnumerable<object>> _deleteUnassignedSampleNumberCommand;

        /// <summary>
        /// Gets the DeleteUnassignedSampleNumberCommand.
        /// </summary>
        public RelayCommand<IEnumerable<object>> DeleteUnassignedSampleNumberCommand
        {
            get
            {
                return _deleteUnassignedSampleNumberCommand ?? (_deleteUnassignedSampleNumberCommand = new RelayCommand<IEnumerable<object>>(
                    ExecuteDeleteUnassignedSampleNumberCommand,
                    CanExecuteDeleteUnassignedSampleNumberCommand));
            }
        }

        private void ExecuteDeleteUnassignedSampleNumberCommand(IEnumerable<object> parameter)
        {
            var selectedSampleNumbers = parameter.OfType<UnassignedSampleNumberViewModel>();

            // Show a message to confirm whether user needs to delete the selected data.
            var dialogMessage = new DialogMessage(string.Format("确认删除所选 {0} 条样本号？该操作将不可恢复！",
                selectedSampleNumbers.Count()), dialogResult =>
                {
                    // This is the CallBack of the DialogMessage.
                    if (dialogResult == MessageBoxResult.Yes)
                    {
                        try
                        {
                            DeleteSelectedSampleNumberDataFromDataSource(selectedSampleNumbers);
                            RemoveSelectedSampleNumberFromCollection(selectedSampleNumbers);
                        }
                        catch (Exception ex)
                        {
                            RequestDisplayErrorMessage(ex.Message);
                        }
                    }
                })
            {
                Button = MessageBoxButton.YesNo,
                Caption = "删除样本号",
                Icon = MessageBoxImage.Question
            };

            Messenger.Default.Send<DialogMessage>(dialogMessage, DeleteDataConfirmMessageToken);
        }

        private bool CanExecuteDeleteUnassignedSampleNumberCommand(IEnumerable<object> parameter)
        {
            if (parameter == null || parameter.Count() == 0)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        /// <summary>
        /// Delete selected sample number data from data source.
        /// </summary>
        private void DeleteSelectedSampleNumberDataFromDataSource(IEnumerable<UnassignedSampleNumberViewModel> selectedSampleNumbers)
        {
            var removedSampleNumbers = selectedSampleNumbers.Select(p => new UnassignedSampleNumber { SampleNumber = p.SampleNumber });
            _unassignedSampleNumberService.Delete(removedSampleNumbers);
        }

        /// <summary>
        /// Remove selected sample number data form collection.
        /// </summary>
        private void RemoveSelectedSampleNumberFromCollection(IEnumerable<UnassignedSampleNumberViewModel> selectedSampleNumbers)
        {
            // Remove selected sample number.
            UnassignedSampleNumberList = new ObservableCollection<UnassignedSampleNumberViewModel>(
                UnassignedSampleNumberList.Where(p => !selectedSampleNumbers.Contains(p)));
        }
    }
}